package com.javapda.util;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;



/**
 * Place to contain helpers associated with GUI production.
 *
 *
 */
public abstract class GuiUtility {

	public static interface TheImageFormat {

	    /** Portable Network Graphics - lossless */
	    public static String PNG = "png";

	    /** Joint Photographic Experts Group format - lossy */
	    public static String JPEG = "jpeg";

	    /** Graphics Interchange Format - lossless, but 256 colour restriction */
	    public static String GIF = "gif";

	}

	/**
	 * Helper method to determine whether or not the current jvm is running in a
	 * headless environment.
	 *
	 * @return
	 */
	public static boolean isSystemHeadless() {
		return System.getProperty("java.awt.headless", "false").equals("true");
	}

	/**
	 * Retrieves an image from a file from the classpath.
	 *
	 * @param path
	 * @return
	 */
	public static BufferedImage getImageFromClasspath(String path) {
		Image image = null;
		java.net.URL imgURL = GuiUtility.class.getResource(path);
//		File file = new File(imgURL.getFile());
//		System.out.println(file.getAbsolutePath());
//		System.out.println(file.exists());
		BufferedImage bufferedImage=null;
		try {
			bufferedImage = ImageIO.read(imgURL);
			if ( bufferedImage != null ) return bufferedImage;
		} catch (IOException e) {
			e.printStackTrace();
		}
//		System.out.println(imgURL);
		ImageIcon imageIcon = new ImageIcon(imgURL, "JED");
		int h = imageIcon.getIconHeight();
		int w = imageIcon.getIconWidth();
		image = (imageIcon).getImage();
//		 image = getThumbnail(image,10,10);
//		 image = getThumbnailHandleTransparency( image, 1.8f );
		 bufferedImage = convert(image, w, h);
		 return bufferedImage;
//		return image;
	}
	
	 public static BufferedImage convert(Image im, int w, int h)
	 {
	    BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
	    Graphics bg = bi.getGraphics();
	    bg.drawImage(im, 0, 0, null);
	    bg.dispose();
	    return bi;
	 }	
	 


	/**
	 * Retrieves the contents of a file from the classpath in the form of an
	 * array of bytes.
	 *
	 * @param path
	 * @return
	 */
	public static byte[] getBytesFromClasspath(String path) {
		java.net.URL imgURL = GuiUtility.class.getResource(path);
		BufferedInputStream bis = null;
		byte[] bytes = null;
		try {
			bis = new BufferedInputStream(imgURL.openStream());
			bytes = FileUtil.convertInputStreamToBytes(bis);
		} catch (IOException e) {
			e.printStackTrace();
			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		return bytes;
	}

	/**
	 * Scales an image and attempts to preserve transparency.
	 *
	 * @param imageToScale
	 * @param scale
	 * @return
	 */
	public static Image getThumbnailHandleTransparency(Image imageToScale,
			float scale) {
		int oldwidth = imageToScale.getWidth(null);
		int oldheight = imageToScale.getHeight(null);
		int newwidth = (int) (scale * oldwidth);
		int newheight = (int) (scale * oldheight);
		int oldcx = oldwidth / 2;
		int oldcy = oldheight / 2;
		int newcx = newwidth / 2;
		int newcy = newheight / 2;
		int[] olddata = new int[oldheight * oldwidth];
		int[] newdata = new int[newheight * newwidth];
		PixelGrabber imagegrabber = new PixelGrabber(imageToScale, 0, 0,
				oldwidth, oldheight, olddata, 0, oldwidth);
		try {
			imagegrabber.grabPixels();
		} catch (InterruptedException e) {
		}

		int A = 0, R = 0, G = 0, B = 0;
		int oldX = 0, oldY = 0;
		for (int y = 0; y < newheight; y++)
			for (int x = 0; x < newwidth; x++) {
				oldX = (int) ((x - newcx) / scale + oldcx);
				oldY = (int) ((y - newcy) / scale + oldcy);
				A = (olddata[oldY * oldwidth + oldX] & 0xFF000000) >> 24;
				if (oldX >= 0 && oldX < oldwidth && oldY >= 0
						&& oldY < oldheight) {
					R = ((olddata[oldY * oldwidth + oldX] & 0x00FF0000) >> 16) * 8 / 10;
					G = ((olddata[oldY * oldwidth + oldX] & 0x0000FF00) >> 8) * 8 / 10;
					B = (olddata[oldY * oldwidth + oldX] & 0x000000FF) * 8 / 10;
				} else {
					R = G = B = 0;
				}
				newdata[y * newwidth + x] = B & 0x000000FF;
				newdata[y * newwidth + x] |= ((G & 0x000000FF) << 8);
				newdata[y * newwidth + x] |= ((R & 0x000000FF) << 16);
				newdata[y * newwidth + x] |= ((A & 0x000000FF) << 24);
			}

		Image transformedImage = Toolkit.getDefaultToolkit()
				.createImage(
						new MemoryImageSource(newwidth, newheight, newdata, 0,
								newwidth));

		return transformedImage;

	}

	/**
	 * Converts an image to a thumbnail image of the requested width and height
	 *
	 * @param imageToScale
	 * @param thumbWidth
	 * @param thumbHeight
	 * @return
	 */
	public static BufferedImage getThumbnail(Image imageToScale, int thumbWidth,
			int thumbHeight) {
		int imageWidth = imageToScale.getWidth(null);
		int imageHeight = imageToScale.getHeight(null);
//		double thumbRatio = (double) thumbWidth / (double) thumbHeight;
//		double imageRatio = (double) imageWidth / (double) imageHeight;
//		if (thumbRatio < imageRatio) {
//			thumbHeight = (int) (thumbWidth / imageRatio);
//		} else {
//			thumbWidth = (int) (thumbHeight * imageRatio);
//		}
		BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight,
				BufferedImage.TYPE_INT_RGB);

		Graphics2D graphics2D = thumbImage.createGraphics();
		graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2D.drawImage(imageToScale, 0, 0, thumbWidth, thumbHeight, null);
//		if (log.isDebugEnabled()) {
//			log.debug("Original: " + imageWidth + "," + imageHeight);
//			log.debug("Request: " + thumbWidth + "," + thumbHeight);
//			log.debug("Thumbnail: " + thumbImage.getWidth(null) + ","
//					+ thumbImage.getHeight(null));
//		}
		return thumbImage;
	}
	
	public static BufferedImage getThumbnail(Image imageToScale, int maxSide ) {
		int width = imageToScale.getWidth(null);
		int height = imageToScale.getHeight(null);
		int thumbWidth = 1;
		int thumbHeight = 1;
		if ( width > height ) {
			thumbWidth = maxSide;
			thumbHeight = (int) (height * ((double)thumbWidth)/width);
		} else {
			thumbHeight = maxSide;
			thumbWidth = (int) (width * ((double)thumbHeight)/height);
		}
		return getThumbnail(imageToScale,thumbWidth,thumbHeight);
		
	}

	public static String getImageInfo(Image bi) {
		StringBuffer sb =new StringBuffer();
		sb.append("Width:"+bi.getWidth(null));
		sb.append("|");
		sb.append("Height:"+bi.getHeight(null));
		sb.append("|");
		sb.append("Source:"+bi.getSource());
		return sb.toString();
	}
	
	public static byte[] convertImageToGifByteArray(BufferedImage img) {
		return convertImageToByteArray(img, TheImageFormat.GIF);
	}
	
	public static byte[] convertImageToJPEGByteArray(BufferedImage img) {
		return convertImageToByteArray(img, TheImageFormat.JPEG);
	}

	public static byte[] convertImageToPngByteArray(BufferedImage img) {
		return convertImageToByteArray(img, TheImageFormat.PNG);
	}
	
	static byte[] convertImageToByteArray(BufferedImage img, String imageFormat) {
		byte[] imageByteArray = null;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			ImageIO.write(img,imageFormat,baos);
			imageByteArray = baos.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return imageByteArray;
		
	}
	
	public static BufferedImage getImageFromByteArray(byte[] imageData) {
		ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
		BufferedImage image = null;
		try {
			image = ImageIO.read(bais);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return image;
	}
	
	public static BufferedImage overlayImage(BufferedImage bi, BufferedImage overlayImage) {
		BufferedImage baseImage = GuiUtility.copyImage(bi);
		Graphics2D g = baseImage.createGraphics();
//        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
        g.drawImage(overlayImage, (baseImage.getWidth()-overlayImage.getWidth())/2, (baseImage.getHeight()-overlayImage.getHeight())/2, null);
        g.dispose();
		return baseImage;
	}
	
	public static BufferedImage copyImage(BufferedImage imageToCopy) {
		BufferedImage bi = null;
		bi = new BufferedImage(imageToCopy.getWidth(null),imageToCopy.getHeight(null),BufferedImage.TYPE_INT_RGB);
		bi.getGraphics().drawImage(imageToCopy,0,0,null);
		return bi;
	}
	
	public static Image loadImageFromStream(InputStream is) throws IOException {
		ByteArrayOutputStream baos = new
		ByteArrayOutputStream();
		            byte buf[] = new byte[8192];
		            int len;
		            while ((len = is.read(buf)) > 0) {
		                baos.write(buf, 0, len);
		            }
		            is.close();
		            Image img = Toolkit.getDefaultToolkit().createImage(baos.toByteArray());

		return img;
	}
}
